home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 August: Tool Chest / Dev.CD Aug 94.toast / Tool Chest / Development Platforms / Macintosh Common Lisp Related / User Contributions / mapforms (code walker).sea / mapforms (code walker) / annotate.lisp < prev    next >
Encoding:
Text File  |  1992-04-21  |  28.3 KB  |  639 lines  |  [TEXT/CCL2]

  1. ;;; -*- Mode:LISP; Package:Language-Tools; Syntax:Common-Lisp -*-
  2. ;;;>>SHARED-MESSAGE
  3. ;;;>
  4. ;;;>******************************************************************************************
  5. ;;;>    This may only be used as permitted under the license agreement under
  6. ;;;>    which it has been distributed, and in no other way.
  7. ;;;>******************************************************************************************
  8. ;;;>
  9. ;;;>
  10. ;;; Written April 1983 by David A. Moon for use by the Common Lisp community
  11. ;;; based on a design by Alan Bawden
  12.  
  13. ;;; Lisp code annotator
  14. ;;; Gathers information on the side-effects and environment dependencies of a form
  15.  
  16. ;--- Common Lisp conversion issues:
  17. ;--- The function lists are completely implementation-dependent right now
  18. ;--- The function lists generally include everything in both ZL and CL global
  19. ;---   packages.  There are probably some SI things needed as well, and some
  20. ;---   ZL things that are never going to be called might be flushed (but why bother?)
  21. ;--- Review the function lists for recent CL changes!
  22.  
  23. ;--- This could generate better code if it distinguished side-effects that cannot
  24. ;--- change variables from side-effects that can change variables.  Admittedly
  25. ;--- RPLACA could always change a variable, due to locatives to value cells,
  26. ;--- but consider the expansion of (SETF (GETF (AREF A I) B) C) which unnecessarily binds
  27. ;--- A and I to temporaries because it thinks that calling SET-GETF could change them.
  28.  
  29. ;; The entry function to this module is ANNOTATE-FORM
  30. ;; The data structures defined on this page are also module interfaces
  31. ;; These are not exported, since they are only used by other tools
  32.  
  33. (EXPORT '(ANNOTATE-FORM *SIMPLE-VARIABLES*))
  34.     ;--- Maybe the defstruct things should be exported, but for now I'm not
  35.     ;--- going to, since probably user-written things shouldn't look at them
  36.  
  37. ;; We deal with two kinds of variables:
  38. ;;  Substituted variables are those that we know the binding of.  We are
  39. ;;   considering substituting the binding for each usage of the variable.
  40. ;;   Only some callers of the annotator deal in substituted variables.
  41. ;;  Ordinary variables are all others.  We are only interested in these
  42. ;;   as a way of possibly partitioning side-effects.
  43.  
  44. ;Nothing warms the heart like simple variables.
  45. ;These are ordinary variables that are known to be unaffected by side-effects;
  46. ;they are guaranteed not to be special, not to be setq'ed, not to be locf'ed,
  47. ;not to be forwarded, and not to be bound (causing name clashes).
  48. ;SETF binds this variable.
  49. (DEFVAR *SIMPLE-VARIABLES* NIL)
  50.  
  51. ;;; A Notepad is used to record information about the effects of executing
  52. ;;; some Lisp code, and the external influences that could affect it.
  53.  
  54. (DEFSTRUCT (NOTEPAD (:TYPE LIST) :CONC-NAME (:DEFAULT-POINTER NOTEPAD))
  55.   (READ NIL)        ;Read operations (dependencies on the side-effects of others)
  56.             ;This is a list of ordinary variables that have been read,
  57.             ;or T if we might have depended on anything.
  58.   (WRITTEN NIL)        ;Write operations (side-effects)
  59.             ;This is a list of ordinary variables that have been written,
  60.             ;or T if we might have changed anything.
  61.   (SUBSTS NIL)        ;List of substituted variables we have seen used
  62.   (CONTROL NIL))    ;Control-structure summary (lowest-priority first)
  63.             ;NIL if we are guaranteed to get all the way to here
  64.             ;COND if we aren't guaranteed to get all the way to here
  65.             ;GO if conditional because of a non-local go or return
  66.             ; This is different from COND because they aren't well-nested
  67.             ;LOOP if we can get here more than once
  68.             ;--- Note that we are distinctly careless about nested control
  69.             ;structures.  Once having seen a loop we assume that everything
  70.             ;after it is inside it, which isn't true.  Main issue for fixing
  71.             ;this is getting the correct scoping of GO and RETURN.
  72.  
  73. ;;; A Varnote is used to record information about the usage(s) of a substituted variable
  74. (DEFSTRUCT (VARNOTE (:TYPE LIST) :CONC-NAME (:DEFAULT-POINTER VARNOTE))
  75.   NAME            ;Variable name.  Must be first so ASSOC can be used.
  76.   (N-USAGES 0)        ;(Static) number of times used
  77.   (VARIABLE-ENV NIL)    ;All variables bound around usages of the variable
  78.   (BLOCK-ENV NIL)    ;All block names extant around usages of the variable
  79.   (TAG-ENV NIL)        ;All go tags extant around usages of the variable
  80.   (NOTEPAD (MAKE-NOTEPAD)))    ;A notepad used to describe what has happened
  81.                 ; before the variable is used.  Set to NIL if we
  82.                 ; discover a reason this variable cannot be substituted.
  83.  
  84. ;;; Operations on notepads
  85.  
  86. (DEFUN NOTE-VARIABLE-READ (NOTEPAD VAR)
  87.   (LET ((READ (NOTEPAD-READ NOTEPAD)))
  88.     (OR (EQ READ T)
  89.     (MEMBER VAR READ)
  90.     (SETF (NOTEPAD-READ NOTEPAD) (CONS VAR READ)))))
  91.  
  92. (DEFSUBST NOTE-ANY-READ (NOTEPAD)
  93.   (SETF (NOTEPAD-READ NOTEPAD) T))
  94.  
  95. (DEFUN NOTE-VARIABLE-WRITTEN (NOTEPAD VAR)
  96.   (LET ((WRITTEN (NOTEPAD-WRITTEN NOTEPAD)))
  97.     (OR (EQ WRITTEN T)
  98.     (MEMBER VAR WRITTEN)
  99.     (SETF (NOTEPAD-WRITTEN NOTEPAD) (CONS VAR WRITTEN)))))
  100.  
  101. (DEFSUBST NOTE-ANY-WRITE (NOTEPAD)
  102.   (SETF (NOTEPAD-WRITTEN NOTEPAD) T))
  103.  
  104. ;True if the code fragments represented by two notepads are independent
  105. ;and hence may be executed in either order.  Maximally conservative
  106. ;in that arbitrary side-effects are assumed to affect all variables
  107. ;(we don't distinguish local variables that haven't been LOCF'ed).
  108. (DEFUN DISJOINT-NOTES (X Y)
  109.   (AND (DISJOINT-SETS (NOTEPAD-WRITTEN X) (NOTEPAD-WRITTEN Y))
  110.        (DISJOINT-SETS (NOTEPAD-READ X) (NOTEPAD-WRITTEN Y))
  111.        (DISJOINT-SETS (NOTEPAD-READ Y) (NOTEPAD-WRITTEN X))))
  112.  
  113. ;True if two sets (of the type used in notepads) are disjoint
  114. (DEFUN DISJOINT-SETS (X Y)
  115.   (COND ((NULL X) T)
  116.     ((NULL Y) T)
  117.     ((EQ X T) NIL)
  118.     ((EQ Y T) NIL)
  119.     (T (LOOP FOR XX IN X NEVER (MEMBER XX Y)))))
  120.  
  121. ;Union of two sets (of the type used in notepads)
  122. (DEFUN JOIN-SETS (X Y)
  123.   (COND ((NULL X) Y)
  124.     ((NULL Y) X)
  125.     ((EQ X T) X)
  126.     ((EQ Y T) Y)
  127.     (T (UNION X Y))))
  128.  
  129. ;Make a copy of a notepad, initially containing the same information
  130. (DEFSUBST FORK-NOTEPAD (NOTEPAD)
  131.   (COPY-LIST NOTEPAD))
  132.  
  133. ;Merge the information from JOINER into JOINEE
  134. (DEFUN JOIN-NOTEPADS (JOINEE JOINER)
  135.   (UNLESS (EQ JOINER JOINEE)    ;merely efficiency
  136.     (SETF (NOTEPAD-READ JOINEE) (JOIN-SETS (NOTEPAD-READ JOINEE) (NOTEPAD-READ JOINER)))
  137.     (SETF (NOTEPAD-WRITTEN JOINEE)
  138.       (JOIN-SETS (NOTEPAD-WRITTEN JOINEE) (NOTEPAD-WRITTEN JOINER)))
  139.     (SETF (NOTEPAD-SUBSTS JOINEE) (UNION (NOTEPAD-SUBSTS JOINEE) (NOTEPAD-SUBSTS JOINER)))
  140.     (CASE (NOTEPAD-CONTROL JOINER)
  141.       ((LOOP)
  142.        (SETF (NOTEPAD-CONTROL JOINEE) 'LOOP))
  143.       ((GO)
  144.        (OR (EQ (NOTEPAD-CONTROL JOINEE) 'LOOP)
  145.        (SETF (NOTEPAD-CONTROL JOINEE) 'GO)))
  146.       ((COND)
  147.        (OR (EQ (NOTEPAD-CONTROL JOINEE) 'LOOP)
  148.        (EQ (NOTEPAD-CONTROL JOINEE) 'GO)
  149.        (SETF (NOTEPAD-CONTROL JOINEE) 'COND))))))
  150.  
  151. ;;; Conditional support
  152.  
  153. ;Execute the body with the notepad indicating locally-conditional execution
  154. ;while being careful about the non-local-conditional and iteration flags
  155. ;Returns no particular value (-not- the value of the body)
  156. (DEFMACRO ANNOTATE-CONDITIONAL (&BODY BODY)
  157.   `(LET ((PREVIOUS-CONTROL (NOTEPAD-CONTROL)))
  158.      (OR PREVIOUS-CONTROL
  159.      (SETF (NOTEPAD-CONTROL) 'COND))
  160.      ,@BODY
  161.      (AND (NOT PREVIOUS-CONTROL)
  162.       (EQ (NOTEPAD-CONTROL) 'COND)
  163.       (SETF (NOTEPAD-CONTROL) NIL))
  164.      NIL))
  165.  
  166. ;;; Iteration support
  167.  
  168. (DEFVAR *IN-LOOP*)        ;NIL in normal once-through execution
  169.                 ;Inside a loop, this is the number of nested levels
  170. (DEFVAR *LOOP-JOIN-QUEUE*)    ;Varnotes seen since the beginning of the loop
  171.                 ;These need to be joined with the notepad
  172.                 ;reflecting the full effects of the loop's body
  173.  
  174. ;Normally fork a notepad, but if inside an iteration, don't bother
  175. ;as everything will be smushed back together at the end anyway
  176. (DEFSUBST FORK-NOTEPAD-MAYBE (NOTEPAD)
  177.   (IF *IN-LOOP* NOTEPAD (FORK-NOTEPAD NOTEPAD)))
  178.  
  179. ;Called when an iteration is entered or exited.  When we get to the end of
  180. ;the loop, feed the notepad that comes out the end of the loop back into
  181. ;the beginning of the loop by joining it into any substitutable variables
  182. ;that were used inside the loop.  When there are nested loops, wait until
  183. ;we get to the end of the outermost one before really draining the queue.
  184. (DEFUN ANNOTATE-ITERATION (ENTER-P)
  185.   (LET ((NOTEPAD *MAPFORMS-STATE*))
  186.     (COND (ENTER-P
  187.        (SETQ *IN-LOOP* (1+ (OR *IN-LOOP* 0)))
  188.        (SETF (NOTEPAD-CONTROL) 'LOOP))
  189.       (T
  190.        (WHEN (ZEROP (SETQ *IN-LOOP* (1- *IN-LOOP*)))
  191.          (SETQ *IN-LOOP* NIL)
  192.          (DOLIST (VARNOTE *LOOP-JOIN-QUEUE*)
  193.            (IF (VARNOTE-NOTEPAD)
  194.            (JOIN-NOTEPADS (VARNOTE-NOTEPAD) NOTEPAD)))
  195.          (SETQ *LOOP-JOIN-QUEUE* NIL))))))
  196.  
  197.  
  198. ;;; Variables bound by ANNOTATE-FORM
  199.  
  200. (DEFVAR *SUBST-ALIST*)    ;List of varnotes for all the substituted variables of interest
  201.  
  202. (DEFVAR *FREE-VARIABLES*)    ;Collect lexically-scoped names used freely
  203. (DEFVAR *FREE-BLOCKS*)        ;..
  204. (DEFVAR *FREE-TAGS*)        ;..
  205. (DEFVAR *REPLICABILITY*)    ;Accumulates return value from ANNOTATE-FORM
  206.  
  207. ;;; Main function
  208.  
  209. ;Given a form, return a notepad for it, and optionally annotate some
  210. ;substitutable variables as well.
  211. ;In addition to the notepad, we return the sets of lexically-scoped names used freely,
  212. ;and the "replicability" of the form, which is the number of times
  213. ;it is worth evaluating it before binding a variable to it (this is 1
  214. ;if this is any form that can't be evaluated multiple times and get
  215. ;the same result as evaluating it once).
  216. ;The free variables don't include the substituted variables.
  217. ;Note: the use of the MAPFORMS state variable herein is unusual, because the
  218. ;value of the variable doesn't change.  Instead it is a structure and we change its fields.
  219. (DEFUN ANNOTATE-FORM (FORM &OPTIONAL (*SUBST-ALIST* NIL))
  220.   (DECLARE (VALUES NOTEPAD FREE-VARIABLES FREE-BLOCKS FREE-TAGS REPLICABILITY))
  221.   (LET ((*IN-LOOP* NIL)
  222.     (*LOOP-JOIN-QUEUE* NIL)
  223.     (*FREE-VARIABLES* NIL)
  224.     (*FREE-BLOCKS* NIL)
  225.     (*FREE-TAGS* NIL)
  226.     (*REPLICABILITY* 1000000))    ;initially "infinity"
  227.     (VALUES (MAPFORMS #'ANNOTATE-FORM-INTERNAL FORM
  228.               :INITIAL-STATE (MAKE-NOTEPAD)
  229.               :BOUND-VARIABLES NIL
  230.               :APPLY-FUNCTION #'ANNOTATE-FORM-AFTER-ARGS
  231.               :ITERATION-HOOK #'ANNOTATE-ITERATION)
  232.         *FREE-VARIABLES*
  233.         *FREE-BLOCKS*
  234.         *FREE-TAGS*
  235.         *REPLICABILITY*)))
  236.  
  237. (DEFUN ANNOTATE-FORM-INTERNAL (FORM KIND USAGE NOTEPAD &AUX VARNOTE (BYPASS NIL))
  238.   (CASE KIND
  239.     (SYMEVAL
  240.       (COND ((MEMBER FORM *MAPFORMS-BOUND-VARIABLES*))
  241.              ;Uninteresting if variable bound inside form being analyzed
  242.         ((SETQ VARNOTE (ASSOC FORM *SUBST-ALIST*))
  243.              ;Accessing a substitutable variable: remember circumstances
  244.          (INCF (VARNOTE-N-USAGES))
  245.          (SETF (VARNOTE-VARIABLE-ENV)
  246.            (UNION (VARNOTE-VARIABLE-ENV) *MAPFORMS-BOUND-VARIABLES*))
  247.          (SETF (VARNOTE-BLOCK-ENV) (UNION (VARNOTE-BLOCK-ENV) *MAPFORMS-BLOCK-NAMES*))
  248.          (SETF (VARNOTE-TAG-ENV) (UNION (VARNOTE-TAG-ENV) *MAPFORMS-GO-TAGS*))
  249.          ;; If in a loop, defer the join until we know everything about the
  250.          ;; loop, since what goes around, comes around
  251.          (COND (*IN-LOOP*
  252.             (PUSHNEW VARNOTE *LOOP-JOIN-QUEUE*))
  253.            ((VARNOTE-NOTEPAD)
  254.             (JOIN-NOTEPADS (VARNOTE-NOTEPAD) NOTEPAD)))
  255.          ;; Remember that we passed by a usage of this variable
  256.          (PUSHNEW FORM (NOTEPAD-SUBSTS)))
  257.             ;Accessing a simple variable: not to be kept track of
  258.         ((MEMBER FORM *SIMPLE-VARIABLES*))
  259.         (T        ;Accessing a free variable
  260.          (PUSHNEW FORM *FREE-VARIABLES*)
  261.          (NOTE-VARIABLE-READ NOTEPAD FORM))))
  262.  
  263.     (SET
  264.       (SETQ *REPLICABILITY* 1)        ;Never do this multiple times
  265.       (COND ((MEMBER FORM *MAPFORMS-BOUND-VARIABLES*))
  266.             ;Uninteresting if variable bound inside form being analyzed
  267.         ((SETQ VARNOTE (ASSOC FORM *SUBST-ALIST*))
  268.             ;Setting a substitutable variable makes it unsubstitutable
  269.          (SETF (VARNOTE-NOTEPAD) NIL))
  270.         (T        ;Setting a free variable
  271.          (PUSHNEW FORM *FREE-VARIABLES*)
  272.          (NOTE-VARIABLE-WRITTEN NOTEPAD FORM))))
  273.  
  274.     (GO
  275.       (SETQ *REPLICABILITY* 1)        ;Never do this multiple times
  276.       (SETF (NOTEPAD-CONTROL) 'GO)    ;Non-local control sequencing has been seen
  277.       (UNLESS (MEMBER FORM *MAPFORMS-GO-TAGS*)
  278.     ;; GO outside of the form being analyzed is a side-effect
  279.     (NOTE-ANY-WRITE NOTEPAD)
  280.     ;; and furthermore is an environmental dependency
  281.     (PUSHNEW FORM *FREE-TAGS*)))
  282.  
  283.     (RETURN-FROM
  284.       (SETQ *REPLICABILITY* 1)        ;Never do this multiple times
  285.       (SETF (NOTEPAD-CONTROL) 'GO)    ;Non-local control sequencing has been seen
  286.       (UNLESS (IF (NULL FORM)        ;Zetalisp version of unnamed RETURN
  287.           (NOT (NULL *MAPFORMS-BLOCK-NAMES*))
  288.           (MEMBER FORM *MAPFORMS-BLOCK-NAMES*))
  289.     ;; RETURN outside of the form being analyzed is a side-effect
  290.     (NOTE-ANY-WRITE NOTEPAD)
  291.     (PUSHNEW FORM *FREE-BLOCKS*)))
  292.  
  293.     (ARBITRARY
  294.       (SETQ *REPLICABILITY* 1)        ;Never do this multiple times
  295.       (NOTE-ANY-WRITE NOTEPAD))
  296.  
  297.     ((QUOTE LET DECLARE))        ;Uninteresting to us
  298.  
  299.     (OTHERWISE        ;Function combination or special form
  300.       (COND ((NOT (OR (NULL KIND) (LISTP KIND)))
  301.          (ERROR "~S unrecognized KIND symbol" KIND))
  302.         ((SETQ BYPASS (AND (SYMBOLP (CAR FORM))
  303.                    (GET (CAR FORM) 'ANNOTATE)))
  304.          (FUNCALL BYPASS FORM USAGE NOTEPAD))
  305.         ((NULL KIND))            ;Function combination
  306.         ((AND (LISTP (CDR KIND)) (EQ (CADR KIND) 'COND))
  307.             ;Special forms that we must understand in detail
  308.             ;(just conditionals now)
  309.          (ERROR "The ~A-type special form ~S does not have an ANNOTATE handler"
  310.             (CADR KIND) (CAR FORM)))
  311.         (T NIL))))    ;Special forms that MAPFORMS will analyze, no effects in or out (yet)
  312.  
  313.   (VALUES NOTEPAD BYPASS))
  314.  
  315. ;Called after analyzing the arguments of a function, the arguments
  316. ;and body of a lambda-combination, or all the subforms of a special form.
  317. ;For a function combination, make our conservative estimate of the effects
  318. ;of running the function, assuming the primitive functions we know about
  319. ;are not redefined by the user to be something else.
  320. (DEFUN ANNOTATE-FORM-AFTER-ARGS (FORM KIND IGNORE NOTEPAD)
  321.   (AND (NULL KIND)            ;Function combination
  322.        (SYMBOLP (CAR FORM))        ;and not a LAMBDA
  323.        (MULTIPLE-VALUE-BIND (CLASS REPLICABILITY)
  324.        (FUNCTION-ANNOTATION-CLASS (CAR FORM))
  325.      (COND ((EQ REPLICABILITY 'TWO-TIMES)
  326.         (SETQ *REPLICABILITY*
  327.               (IF (> *REPLICABILITY* 2)
  328.               2        ;This thing could be done twice
  329.               1)))        ;But two of them should only be done once
  330.            ((NULL REPLICABILITY)    ;Don't know, do it only once
  331.         (SETQ *REPLICABILITY* 1)))
  332.      (CASE CLASS
  333.        (SIMPLE )            ;No side-effects in or out
  334.        (READER            ;Depends on environment but doesn't change anything
  335.         (NOTE-ANY-READ NOTEPAD))
  336.        (OTHERWISE            ;Default is to assume that it could do anything
  337.         (NOTE-ANY-WRITE NOTEPAD)))))
  338.   NOTEPAD)
  339.  
  340. ;;; Procedural knowledge of conditional and iteration special forms
  341.  
  342. ; Note that these functions will freely cdr off the end of the form when
  343. ; that makes no difference to the ultimate result, to simplify the coding.
  344.  
  345. (DEFPROP AND AND-OR-ANNOTATE ANNOTATE)
  346. (DEFPROP OR AND-OR-ANNOTATE ANNOTATE)
  347. (DEFUN AND-OR-ANNOTATE (FORM IGNORE NOTEPAD)
  348.   (MAPFORMS-1 (CADR FORM))        ;First clause executed unconditionally
  349.   (ANNOTATE-CONDITIONAL            ;Everything after this is conditional
  350.     (ANNOTATE-FORMS (CDDR FORM))))
  351.  
  352. ;The hair in COND is primarily that the consequents of one clause
  353. ;neither preceed nor follow the consequents of another, while the antecedents
  354. ;follow each other.  Thus we must split the notepad into multiple independent pads.
  355. (DEFUN (:PROPERTY COND ANNOTATE) (FORM IGNORE NOTEPAD)
  356.   (MAPFORMS-1 (CAADR FORM))        ;First antecedent executed unconditionally
  357.   (ANNOTATE-CONDITIONAL            ;Everything after this is conditional
  358.     (LOOP FOR (ANTE . CONSE) IN (CDR FORM)    ;Iterate over clauses
  359.       WITH SPLITS = NIL        ;Collect split-off notepads for consequents
  360.       AS FIRST-CLAUSE = T THEN NIL DO
  361.       (OR FIRST-CLAUSE
  362.       (MAPFORMS-1 ANTE))        ;Do antecedent if not done already
  363.       (UNLESS (NULL CONSE)        ;Do consequents with a separate notepad
  364.     (LET ((SPLIT (FORK-NOTEPAD-MAYBE NOTEPAD)))
  365.       (PUSH SPLIT SPLITS)
  366.       (ANNOTATE-SPLIT-FORMS CONSE SPLIT)))
  367.       FINALLY                ;Merge all the consequents consequences
  368.         (DOLIST (SPLIT SPLITS)
  369.       (JOIN-NOTEPADS NOTEPAD SPLIT)))))
  370.  
  371. ;IF is just a simpler version of COND
  372. (DEFUN (:PROPERTY IF ANNOTATE) (FORM IGNORE NOTEPAD)
  373.   (MAPFORMS-1 (CADR FORM) 'TEST)    ;The test is executed unconditionally
  374.   (ANNOTATE-CONDITIONAL
  375.     (IF (NULL (CDDDR FORM))        ;Check for 1-arm case (merely efficiency)
  376.     (MAPFORMS-1 (CADDR FORM))
  377.     (LET ((SPLIT (FORK-NOTEPAD-MAYBE NOTEPAD)))
  378.       (MAPFORMS-1 (CADDR FORM))
  379.       (ANNOTATE-SPLIT-FORMS (CDDDR FORM) SPLIT)
  380.       (JOIN-NOTEPADS NOTEPAD SPLIT)))))
  381.  
  382. ;Annotate a list of forms, being careless about the USAGE
  383. ;Fix this if we ever start depending on USAGE (will need to add more args)
  384. (DEFUN ANNOTATE-FORMS (LIST)
  385.   (DOLIST (FORM LIST)
  386.     (MAPFORMS-1 FORM)))
  387.  
  388. ;Annotate a list of forms with a different notepad, being careless about the USAGE
  389. (DEFUN ANNOTATE-SPLIT-FORMS (LIST NOTEPAD)
  390.   (LET ((*MAPFORMS-STATE* NOTEPAD))
  391.     (DOLIST (FORM LIST)
  392.       (MAPFORMS-1 FORM))))
  393.  
  394. ;;; Knowledge about various functions (not special forms)
  395.  
  396. ;; We have a little bit of knowledge of the primitive functions of the
  397. ;; language: 
  398.  
  399. ;; Notice that we know nothing about any function that has any side effects.
  400. ;; This is because all functions with side effects are equally uncontrolled.
  401. ;; There is no point in going through the exercize of dividing them up into
  402. ;; classes according to who can effect whom on a machine where RPLACA can be
  403. ;; used to store into a local variable, or into an array...
  404.  
  405. ;; Notice that both classes of functions (simple and reader) have the
  406. ;; property that it is always safe to not call them at all if it turns
  407. ;; out that they are being called for effect.
  408.  
  409. ;; The attributes of a function are recorded in a bit mask on the
  410. ;; FUNCTION-ATTRIBUTES property of the name of the function.
  411. ;; The default attributes for things we don't know about have none of these
  412. ;; bits set, which means that they may have arbitrary side-effects, may
  413. ;; depend on anything in the environment, and may be arbitrarily expensive to compute.
  414. ;; This bit mask used to be defined with a :FIXNUM defstruct, but Common
  415. ;; Lisp doesn't have such features, so do it by hand.
  416.  
  417. (DEFCONSTANT MANY-TIMES-ATTRIBUTE 1)    ;cheaper to compute than to bind a variable
  418. (DEFCONSTANT TWO-TIMES-ATTRIBUTE 2)    ;worth computing twice before binding a variable
  419. (DEFCONSTANT SIMPLE-ATTRIBUTE 4)    ;neither affects nor depends on the environment
  420. (DEFCONSTANT REDUCIBLE-ATTRIBUTE #o10)    ;SIMPLE and may be constant-folded (single-valued)
  421. (DEFCONSTANT READER-ATTRIBUTE #o20)    ;depends on the environment but doesn't change it
  422.  
  423. (DEFPARAMETER INTENTIONALLY-UNDEFINED-FUNCTIONS        ;Suppress warning for these
  424.       #+LISPM ())
  425.  
  426. (DEFMACRO PUT-ATTRIBUTES (F &REST ATTRIBUTES)
  427.   `(PROGN
  428.      (UNLESS (FBOUNDP ,F)
  429.        (UNLESS (MEMBER ,F INTENTIONALLY-UNDEFINED-FUNCTIONS)
  430.      (WARN "PUT-ATTRIBUTES of ~S, which is not a defined function; may be a typo." ,F)))
  431.      (SETF (GET ,F 'FUNCTION-ATTRIBUTES)
  432.        (LOGIOR (GET ,F 'FUNCTION-ATTRIBUTES 0)
  433.            ,@(MAPCAR #'(LAMBDA (NAME) (INTERN (STRING-APPEND NAME "-ATTRIBUTE")
  434.                               "LANGUAGE-TOOLS"))
  435.                  ATTRIBUTES)))))
  436.  
  437. ;The first value is:
  438. ; SIMPLE - neither affects nor depends on the environment
  439. ; READER - depends on the environment but doesn't change it
  440. ; WRITER - may change the environment (and may also depend on it)
  441. ;The second value is:
  442. ; NIL - expensive to compute
  443. ; TWO-TIMES - worth computing twice rather than binding a variable
  444. ; MANY-TIMES - worth computing any number of times rather than binding a variable
  445. (DEFUN FUNCTION-ANNOTATION-CLASS (FUNCTION)
  446.   (IF (SYMBOLP FUNCTION)
  447.       (LET ((ATTRIBUTES (GET FUNCTION 'FUNCTION-ATTRIBUTES 0)))
  448.     (VALUES (COND ((LOGTEST SIMPLE-ATTRIBUTE ATTRIBUTES) 'SIMPLE)
  449.               ((LOGTEST READER-ATTRIBUTE ATTRIBUTES) 'READER)
  450.               (T 'WRITER))
  451.         (COND ((LOGTEST MANY-TIMES-ATTRIBUTE ATTRIBUTES) 'MANY-TIMES)
  452.               ((LOGTEST TWO-TIMES-ATTRIBUTE ATTRIBUTES) 'TWO-TIMES))))
  453.       'WRITER))
  454.  
  455. ;;; Store the function attributes
  456.  
  457. ;These are compiled functions so they will run fast.  They are only called once
  458. (DEFUN ATTR-SIMPLE-REDUCIBLE (FNS)
  459.   (DOLIST (F FNS)
  460.     (PUT-ATTRIBUTES F SIMPLE REDUCIBLE)))
  461.  
  462. (DEFUN ATTR-SIMPLE (FNS)
  463.   (DOLIST (F FNS)
  464.     (PUT-ATTRIBUTES F SIMPLE)))
  465.  
  466. (DEFUN ATTR-READER (FNS)
  467.   (DOLIST (F FNS)
  468.     (PUT-ATTRIBUTES F READER)))
  469.  
  470. (DEFUN ATTR-MANY-TIMES (FNS)
  471.   (DOLIST (F FNS)
  472.     (PUT-ATTRIBUTES F MANY-TIMES)))
  473.  
  474. (DEFUN ATTR-TWO-TIMES (FNS)
  475.   (DOLIST (F FNS)
  476.     (PUT-ATTRIBUTES F TWO-TIMES)))
  477.  
  478. ;; Simple functions are totally uneffected by side effects.  Note that anything
  479. ;; that conses is liable to be sensitive to the default-cons-area, so isn't
  480. ;; included here (consing of bignums/flonums excepted).
  481. ;; Reducible functions have the further property that they only return one value
  482. ;; and anything else (if anything) needed to ensure that an expression made up
  483. ;; of nothing but reducible functions and constants might as well be run at
  484. ;; compile time.
  485.  
  486. ;; The simple and reducible functions
  487. (ATTR-SIMPLE-REDUCIBLE
  488.        '(   * + - / 1+ 1- /= < <= = > >=
  489.          ZL:/ ZL:\\ ZL:\\\\ ZL:^   ;probably some macros expand into these
  490.          ABS ACOS ACOSH ZL:ADD1 ALPHA-CHAR-P ALPHANUMERICP
  491.          ARRAYP ZL:ASCII ASH ASIN ASINH ATAN ATANH ZL:ATAN ZL:ATAN2 ATOM
  492.          ZL:BIGP BIT-VECTOR-P BOOLE BOTH-CASE-P BYTE-POSITION BYTE-SIZE BYTE
  493.          CEILING CHARACTERP
  494.          CHAR-BIT CHAR-BITS CHAR-CODE CHAR-DOWNCASE CHAR-EQUAL CHAR-FONT
  495.          CHAR-GREATERP CHAR-INT CHAR-LESSP CHAR-NAME CHAR-NOT-EQUAL CHAR-NOT-GREATERP
  496.          CHAR-NOT-LESSP CHAR-UPCASE
  497.          CHAR/= CHAR<= CHAR< CHAR= CHAR>= CHAR> CHAR CHAR CHAR
  498.          CIS ZL:CLOSUREP CODE-CHAR COMMONP COMPILED-FUNCTION-P
  499.          COMPLEXP CONJUGATE CONSP CONSTANTP COS COSD COSH
  500.          ZL:DATA-TYPE DENOMINATOR ZL:DEPOSIT-BYTE DEPOSIT-FIELD ZL:DIFFERENCE DPB
  501.          DYNAMIC-CLOSURE-P
  502.          EQ EQL ERRORP EVENP EXP EXPT
  503.          FALSE FCEILING FFLOOR ZL:FIX ZL:FIXR ZL:FIXP FLOAT FLOATP FLOOR
  504.          ZL:FLONUMP FROUND FTRUNCATE FUNCTIONP
  505.          GCD ZL:GET-PNAME ZL:GETCHAR ZL:GETCHARN ZL:GREATERP GRAPHIC-CHAR-P
  506.          ZL:HAIPART ZL:HAULONG HASH-TABLE-P
  507.          IDENTITY IMAGPART INT-CHAR INTEGERP INTEGER-LENGTH IGNORE ISQRT
  508.          KEYWORDP
  509.          LCM LDB LDB-TEST ZL:LESSP LEXICAL-CLOSURE-P LISTP ZL:LOAD-BYTE ZL:LOCATIVEP
  510.          LOG LOGAND LOGANDC1 LOGANDC2 LOGBITP LOGCOUNT LOGEQV LOGIOR LOGNAND LOGNOR
  511.          LOGNOT LOGORC1 LOGORC2 LOGTEST LOGXOR LOWER-CASE-P LSH
  512.          MAKE-CHAR MASK-FIELD MAX MIN ZL:MINUS MINUSP MOD
  513.          NAME-CHAR NLISTP NOT NSYMBOLP NULL NUMBERP NUMERATOR
  514.          ODDP
  515.          PATHNAMEP PHASE ZL:PLUS PLUSP
  516.          ZL:QUOTIENT
  517.          RANDOM-STATE-P RATIONALP READTABLEP REALPART REM REMAINDER ROT ROUND
  518.          SAMEPNAMEP SET-CHAR-BIT SIGNUM SIN SIND SINH
  519.          #+CADR SMALL-FLOAT #+CADR SMALL-FLOATP
  520.          SQRT STANDARD-CHAR-P STREAMP STRING-CHAR-P STRINGP ZL:SUB1 ZL:SUBRP SYMBOLP
  521.          TAN TANH TIME-DIFFERENCE TIME-INCREMENT TIME-LESSP ZL:TIMES TRUE TYPEP
  522.          UPPER-CASE-P VECTORP
  523.          ZEROP))
  524.  
  525. ;; The simple but not reducible functions
  526. (ATTR-SIMPLE '(VALUES VALUES-LIST))
  527.  
  528. ;; Reader functions do not have side effects, but they are potentially
  529. ;; sensitive to them.  Functions that create locatives are here because it's not
  530. ;; clear that you can't get a different locative (not EQ) if someone performs
  531. ;; some structure-fowarding.  Any function that takes a functional argument
  532. ;; (like FUNCALL, MAPCAR or ASS) should not be here since the properties of the
  533. ;; function are unknown.  I/O operations are side effects.  So is asking what
  534. ;; time it is (the TIME function).  When in doubt, leave it out!
  535. ;; The reason it works for consing functions to be here is that they do not
  536. ;; have the TWO-TIMES and MANY-TIMES attributes, so calls to them will not
  537. ;; be replicated, just shuffled around.  And it is considered okay to
  538. ;; remove consing during optimization.  Consing functions are not SIMPLE
  539. ;; because of the variable DEFAULT-CONS-AREA.
  540.  
  541. (ATTR-READER
  542.        '(ACONS ADJOIN ALOC
  543.          ALPHALESSP  ;because of ALPHABETIC-CASE-AFFECTS-STRING-COMPARISON
  544.          ZL:AP-1 ZL:AP-2 #+CADR ZL:AP-3 ZL:AP-LEADER
  545.          APPEND ZL:AR-1 ZL:AR-2 #+CADR ZL:AR-3 AREF ZL:ARG ARGLIST
  546.          ARGS-INFO ZL:ARRAY-#-DIMS ZL:ARRAY-ACTIVE-LENGTH ZL:ARRAY-DIMENSION-N
  547.          ARRAY-DIMENSIONS ARRAY-DISPLACED-P ARRAY-ELEMENT-SIZE ARRAY-HAS-LEADER-P
  548.          ARRAY-IN-BOUNDS-P ARRAY-INDEXED-P ARRAY-INDIRECT-P ARRAY-LEADER
  549.          ARRAY-LEADER-LENGTH ZL:ARRAY-LENGTH ARRAY-TYPE ZL:ARRAYDIMS
  550.          ASSOC ASSOC-IF ASSOC-IF-NOT ASSQ
  551.          BIT BOUNDP BUTLAST
  552.          CAAAAR CAAADR CAAAR CAADAR CAADDR CAADR CAAR CADAAR CADADR CADAR
  553.          CADDAR CADDDR CADDR CADR CAR ZL:CAR-LOCATION CDAAAR CDAADR CDAAR
  554.          CDADAR CDADDR CDADR CDAR CDDAAR CDDADR CDDAR CDDDAR CDDDDR CDDDR
  555.          CDDR CDR CHAR CHARACTER CIRCULAR-LIST CLOSURE CLOSURE-ALIST CLOSURE-FUNCTION
  556.          CLOSURE-VARIABLES CONS COPY-ALIST COPY-LIST COPY-LIST* COPY-READTABLE
  557.          COPY-SEQ COPY-SYMBOL COPY-TREE COUNT COUNT-IF COUNT-IF-NOT
  558.          DEBUGGING-INFO DOCUMENTATION
  559.          EIGHTH ELT EQUAL EQUALP ZL:EXPLODE ZL:EXPLODEC ZL:EXPLODEN
  560.          FBOUNDP FDEFINEDP FDEFINITION FIFTH
  561.          FIND FIND-IF FIND-IF-NOT ZL:FIND-POSITION-IN-LIST ZL:FIND-POSITION-IN-LIST-EQUAL
  562.          FIRST ZL:FIRSTN ZL:FLATC ZL:FLATSIZE FLAVOR-ALLOWS-INIT-KEYWORD-P
  563.          FOURTH ZL:FSYMEVAL ZL:FUNCTION-CELL-LOCATION
  564.          G-L-P GET ZL:GET GETF GET-HANDLER-FOR GET-PROPERTIES GETHASH ZL:GETL
  565.          INTERSECTION
  566.          LAST LDIFF LENGTH LIST LIST-ARRAY-LEADER LIST-LENGTH LIST*
  567.          ZL:LISTARRAY ZL:LISTIFY LOCATE-IN-CLOSURE LOCATE-IN-INSTANCE
  568.          MAKE-ARRAY MAKE-BROADCAST-STREAM MAKE-CONCATENATED-STREAM MAKE-ECHO-STREAM
  569.          ZL:MAKE-EQUAL-HASH-TABLE MAKE-HASH-TABLE MAKE-LIST MAKE-PLANE
  570.          MAKE-RANDOM-STATE MAKE-SEQUENCE MAKE-STRING MAKE-STRING-INPUT-STREAM
  571.          MAKE-STRING-OUTPUT-STREAM MAKE-SYMBOL MAKE-SYNONYM-STREAM MAKE-TWO-WAY-STREAM
  572.          MEMBER MEMBER-IF MEMBER-IF-NOT MEMQ
  573.          NAMED-STRUCTURE-P NAMED-STRUCTURE-SYMBOL NCONS NINTH NLEFT NTH NTHCDR
  574.          ZL:PACKAGE-CELL-LOCATION PAIRLIS PKG-FIND-PACKAGE ZL:PLIST
  575.          POSITION POSITION-IF POSITION-IF-NOT ZL:PROPERTY-CELL-LOCATION
  576.          RASSOC RASSOC-IF RASSOC-IF-NOT ZL:RASSQ REMOVE REMOVE-IF REMOVE-IF-NOT REMQ
  577.          REST REVERSE 
  578.          SBIT SCHAR SEARCH SECOND SEVENTH SIXTH STREAM-ELEMENT-TYPE
  579.         ;String ops are readers because you can side-effect chars of a string
  580.          STRING STRING-APPEND STRING-CAPITALIZE
  581.          STRING-COMPARE STRING-DOWNCASE STRING-EQUAL STRING-GREATERP
  582.          STRING-LEFT-TRIM STRING-LENGTH STRING-LESSP STRING-NOT-EQUAL
  583.          STRING-NOT-GREATERP STRING-NOT-LESSP STRING-PLURALIZE
  584.          ZL:STRING-REVERSE ZL:STRING-REVERSE-SEARCH ZL:STRING-REVERSE-SEARCH-CHAR
  585.          ZL:STRING-REVERSE-SEARCH-NOT-CHAR ZL:STRING-REVERSE-SEARCH-NOT-SET
  586.          ZL:STRING-REVERSE-SEARCH-SET STRING-RIGHT-TRIM STRING-SEARCH
  587.          STRING-SEARCH-CHAR STRING-SEARCH-NOT-CHAR STRING-SEARCH-NOT-SET STRING-SEARCH-SET
  588.          STRING-TRIM STRING-UPCASE STRING/= STRING<= STRING< STRING= STRING>= STRING>
  589.          SUBLIS SUBST SUBST-IF SUBST-IF-NOT SUBSTITUTE SUBSTITUTE-IF SUBSTITUTE-IF-NOT
  590.          SUBSTRING SVREF SXHASH SYMBOL-FUNCTION SYMBOL-NAME SYMBOL-PACKAGE SYMBOL-PLIST
  591.          SYMBOL-VALUE-IN-CLOSURE SYMBOL-VALUE-IN-INSTANCE
  592.          ZL:SYMEVAL ZL:SYMEVAL-IN-CLOSURE ZL:SYMEVAL-IN-INSTANCE
  593.          TAILP TENTH THIRD TREE-EQUAL
  594.          UNION
  595.          VALUE-CELL-LOCATION
  596.          XCONS))
  597.  
  598. ;; These functions have the property that is is always cheaper to recompute
  599. ;; them rather that binding a variable the their value.  That is,
  600. ;;  (let ((x (car y))) <exp>) will be more expensive than simply replacing
  601. ;; every occurence of x by (car y) in <exp>.
  602. ;; NOT, NULL, ATOM, ENDP, and LISTP are in this list because of the assumption that they
  603. ;; are most likely being used as predicates rather than for value, and therefore
  604. ;; will disappear into branch instructions rather than generating extra code.
  605. ;; Note that on the 3600 variable-binding is cheaper relative to CAR/CDR
  606.  
  607. #+CADR
  608. (ATTR-MANY-TIMES '(CAAR CADR CAR CDAR CDDR CDR))
  609.  
  610. (ATTR-MANY-TIMES '(ATOM ENDP FALSE LISTP NLISTP NOT NULL TRUE))
  611.  
  612. ;; Similar to the above, it has been determined that these single argument
  613. ;; functions (all MISC instructions) can be substituted into a body UP TO two
  614. ;; times, beyond that it is better to have the local variable.
  615. ;; On the 3600, this list is empty since variable-binding is almost free
  616. ;; and some of these operations are actually more expensive (not microcoded)
  617.  
  618. #+CADR
  619. (ATTR-TWO-TIMES
  620.        '(1+ ZL:1+$ 1- ZL:1-$
  621.          ABS ZL:ADD1 ZL:ARRAY-ACTIVE-LENGTH ARRAY-HAS-LEADER-P ZL:ARRAY-LENGTH ARRAYP
  622.          BOUNDP
  623.          CAAAAR CAAADR CAAAR CAADAR CAADDR CAADR CADAAR CADADR CADAR CADDAR
  624.          CADDDR CADDR CDAAAR CDAADR CDAAR CDADAR CDADDR CDADR CDDAAR CDDADR
  625.          CDDAR CDDDAR CDDDDR CDDDR
  626.          EVENP
  627.          FBOUNDP ZL:FIX ZL:FIXP FLOAT FLOATP ZL:FSYMEVAL
  628.          G-L-P ZL:GET-PNAME
  629.          ZL:HAULONG
  630.          ZL:MINUS            ;- of one argument should be treated specially?
  631.          MINUSP
  632.          NSYMBOLP NUMBERP
  633.          ODDP
  634.          PLUSP
  635.          SMALL-FLOAT STRINGP ZL:SUB1 SYMBOLP
  636.          SYMBOL-FUNCTION SYMBOL-PRINT-NAME SYMBOL-VALUE
  637.          ZL:SYMEVAL
  638.          ZEROP))
  639.